/********************************************************************************
 * @file   gkt_compiler_gcc.h
 * @brief  GCC Compiler header file
 * @date   8/Oct/2018
 ********************************************************************************/
 
#ifndef GKT_COMPILER_GCC_H
#define GKT_COMPILER_GCC_H

#ifndef __ASM
#define __ASM	__asm
#endif

#ifndef __INLINE
#define __INLINE	__attribute__((__always_inline__)) inline
#endif

#ifndef __STATIC_INLINE
#define __STATIC_INLINE	static __attribute__((__always_inline__)) inline
#endif

#ifndef __NO_RETURN
#define __NO_RETURN	__attribute__((__noreturn__))
#endif

#ifndef __USED
#define __USED	__attribute__((__used__))
#endif

#ifndef __UNUSED
#define __UNUSED	__attribute__((__unused__))
#endif

#ifndef __WEAK
#define __WEAK	__attribute__((__weak__))
#endif

#ifndef __ALIAS
#define __ALIAS(x)	__attribute__((__alias__(#x)))
#endif

#ifndef __ALIGNED
#define __ALIGNED(x)	__attribute__((aligned(x)))
#endif

#ifndef __PACKED
#define __PACKED	__attribute__((packed, aligned(1)))
#endif

#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT	struct __attribute__((packed, aligned(1)))
#endif

#ifndef __UNALIGNED_UINT32
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#pragma GCC diagnostic pop
#define __UNALIGNED_UINT32(x)	(((struct T_UINT32 *)(x))->v)
#endif

#ifndef __SECTION
#define __SECTION(name)	__attribute__((__section__(#name)))
#endif

#define __SECTION_TEXT	__SECTION(.text)
#define __SECTION_RODATA	__SECTION(.rodata)
#define __SECTION_DATA	__SECTION(.data)
#define __SECTION_BSS	__SECTION(.bss)

#ifndef __NAKED
#define __NAKED	__attribute__((__naked__))
#endif

#ifndef __RESULT_CHECK
#define __RESULT_CHECK __attribute__((__warn_unused_result__))
#endif

#ifndef __FORMAT_CHECK
#define __FORMAT_CHECK(check_type, string_index, first_to_check)	\
	__attribute__((__format__(check_type, string_index, first_to_check)))
#endif

/* branch prediction optimize */
#define __LIKELY(exp)	__builtin_expect(!!(exp), 1)
#define __UNLIKELY(exp)	__builtin_expect(!!(exp), 0)

#define __MAX(a, b)	\
	({	\
		typeof(a) __max_a = a;	\
		typeof(b) __max_b = b;	\
		(void)(&__max_a == &__max_b);	\
		(__max_a > __max_b) ? __max_a : __max_b;	\
	})

#define __MIN(a, b)	\
	({	\
		typeof(a) __min_a = a;	\
		typeof(b) __min_b = b;	\
		(void)(&__min_a == &__min_b);	\
		(__min_a < __min_b) ? __min_a : __min_b;	\
	})

/* byte order */
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define GKT_LITTLE_ENDIAN	1
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define GKT_LITTLE_ENDIAN	0
#else
#error "unknown byte order / endian"
#endif

#endif	/* GKT_COMPILER_GCC_H */


